package com.leadnews.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.SensitiveWordUtil;
import com.leadnews.wemedia.mapper.WmNewsMapper;
import com.leadnews.wemedia.mapper.WmSensitiveMapper;
import com.leadnews.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    /**
     * 自动审核文本
     *
     * @param id 自媒体文章id
     */
    @Override
    @Async  //标明当前方法是一个异步方法
    public void autoScanWmNews(Integer id) {
        // 1.查询自媒体文章信息
        WmNews wmNews = wmNewsMapper.selectById(id);

        if (wmNews == null) {
            log.error("当前文章不存在");
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不存在");
        }
        // 2.判断文章是否为提交状态
        if (wmNews.getStatus() != WmNews.Status.SUBMIT.getCode()) {
            log.error("当前文章不是提交状态");
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不是提交状态");
        }

        //从内容中提取纯文本内容和图片
        Map<String,Object> textAndImages = handleTextAndImages(wmNews);
        //自管理的敏感词过滤
        boolean isSensitive = handleSensitiveScan((String) textAndImages.get("content"), wmNews);
        if(!isSensitive) return;

        // 3.审核文章
        // 3.1 从内容中提取文本和图片内容

        // 存储纯文本内容
        StringBuilder text = new StringBuilder();
        // 存储图片内容
        List<String> images = new ArrayList<>();

        // 从自媒体文章内容中提取文本和图片
        if (wmNews.getContent() != null && !wmNews.getContent().isEmpty()) {
            List<Map> maps = JSON.parseArray(wmNews.getContent(), Map.class);
            maps.forEach(map -> {
                if (map.get("type").equals("text")) {
                    text.append(map.get("value"));
                } else if (map.get("type").equals("image")) {
                    images.add(map.get("value").toString());
                }
            });
        }

        log.info("文本内容：{}", text);
        log.info("图片内容：{}", images);

        try {
            // 3.2 调用阿里云接口进行检测
            Map map = greenTextScan.greenTextScanStrongVersion(text.toString());
            log.info("阿里云返回结果：{}", map);
            if (map != null && "pass".equals(map.get("suggestion"))) {
                // 4.审核成功
                // 4.1 检测图片
                for (String imageUrl : images) {
                    Map map1 = greenImageScan.imageScanStrongLocalVersion(imageUrl);
                    log.info("阿里云返回结果：{}", map1);
                    if (map1 != null && map1.get("suggestion").equals("block")) {
                        // 4.2 图片审核失败
                        // 4.2 1 修改文章状态为审核未通过
                        wmNews.setStatus(WmNews.Status.FAIL.getCode());
                    }
                }
            } else if (map != null && map.get("suggestion").equals("review")) {
                // 4.审核失败
                // 4.1 修改文章状态为待审核
                wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                wmNewsMapper.updateById(wmNews);
                // 4.2 添加审核失败原因
                wmNews.setReason("审核未通过");
                wmNewsMapper.updateById(wmNews);
            }
        } catch (Exception e) {
            throw new RuntimeException("内容检测失败！");
        }
    }


    /**
     * 1。从自媒体文章的内容中提取文本和图片
     * 2.提取文章的封面图片
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {

        //存储纯文本内容
        StringBuilder stringBuilder = new StringBuilder();

        List<String> images = new ArrayList<>();

        //1。从自媒体文章的内容中提取文本和图片
        if(StringUtils.isNotBlank(wmNews.getContent())){
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : maps) {
                if (map.get("type").equals("text")){
                    stringBuilder.append(map.get("value"));
                }

                if (map.get("type").equals("image")){
                    images.add((String) map.get("value"));
                }
            }
        }
        //2.提取文章的封面图片
        if(StringUtils.isNotBlank(wmNews.getImages())){
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content",stringBuilder.toString());
        resultMap.put("images",images);
        return resultMap;

    }
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    /**
     * 自管理的敏感词审核
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitiveScan(String content, WmNews wmNews) {

        boolean flag = true;

        //获取所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (!map.isEmpty()) {
            updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容" + map);
            flag = false;
        }

        return flag;
    }


    /**
     * 修改文章内容
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }
}
